export const ENV_ENUM = {
	dev: 'https://minedev.yhdja.com/api',
	test: 'https://minetest.yhdja.com/api',
	pre: 'https://minepre.yhdja.com/api',
};
const ossPolicyPath = '/admin/aliyunOss/oss-policy';
const ossFilePath = '/admin/aliyunOss/oss-full-path';
const env = uni.getStorageSync('currentEnv') || 'dev';
const token = uni.getStorageSync('token');
const tenantId = uni.getStorageSync('tenantId');
const projectId = uni.getStorageSync('projectId');
const baseUrl = ENV_ENUM[env];

/**
 * 生成UUID
 * @returns {string} UUID
 */
export const generateUUID = () => {
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
		const random = (Math.random() * 16) | 0; // 生成0-15的随机数
		const value = char === 'x' ? random : (random & 0x3) | 0x8; // 确保y的值符合UUID标准
		return value.toString(16); // 转换为16进制
	});
};

/**
 * 递归树形结构
 * @param treeData {array} 树状数组
 * @param value {string} 选中的值
 * @param checkedKey 选中状态字段名
 * @param valueKey 值字段名
 * @param childrenKey 子代数组字段名
 * @returns {array} 处理完后的树状数组
 */
export const checkTreeData = (treeData, value, checkedKey = 'checked', valueKey = 'value', childrenKey = 'children') => {
	// 如果传入的树形数据为空，直接返回空数组
	if (!Array.isArray(treeData) || treeData.length === 0) {
		return [];
	}

	// 定义递归处理函数
	const recursiveProcess = (nodes) => {
		return nodes.map((node) => {
			// 删除当前节点的 `checkedKey` 字段
			delete node[checkedKey];

			// 如果传入了具体值，设置目标节点的 `checkedKey` 字段为 `true`
			if (value && node[valueKey] === value) {
				node[checkedKey] = true;
			}

			// 如果存在子节点，递归处理子节点
			if (Array.isArray(node[childrenKey]) && node[childrenKey].length > 0) {
				node[childrenKey] = recursiveProcess(node[childrenKey]);
			}

			return node;
		});
	};

	// 返回处理后的树形数据
	return recursiveProcess(treeData);
};

/**
 * 时间格式化
 * @param date {Date | number | string} 时间对象 | 时间戳 | 时间字符串
 * @param format {string} 时间格式
 * @returns {string} 格式化后的时间字符串
 */
const dateTimeFormat = (date, format = 'yyyy-MM-dd HH:mm:ss') => {
	// 如果 date 是字符串类型的时间戳，转为数字类型
	if (typeof date === 'string' && !isNaN(date)) {
		date = parseInt(date, 10);
	}
	// 如果是时间字符串，尝试转换为 Date 对象
	if (typeof date === 'string' && isNaN(date)) {
		date = new Date(date.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3').replace(/(\d{2})(\d{2})(\d{2})/, '$1:$2:$3'));
	}
	// 如果是时间戳，先转换为 Date 对象
	if (typeof date === 'number') {
		date = new Date(date);
	}

	if (!(date instanceof Date) || isNaN(date)) {
		throw new Error('无效的日期参数');
	}

	const padZero = (num) => (num < 10 ? '0' + num : num);

	const replacements = {
		yyyy: date.getFullYear(),
		MM: padZero(date.getMonth() + 1),
		dd: padZero(date.getDate()),
		HH: padZero(date.getHours()),
		hh: padZero(date.getHours() % 12 || 12),
		mm: padZero(date.getMinutes()),
		ss: padZero(date.getSeconds()),
	};

	// 替换 format 中的占位符
	return format.replace(/yyyy|MM|dd|HH|hh|mm|ss/g, (match) => replacements[match]);
};

/**
 * 获取文件名信息
 * @param fileFullName {string} 文件全名
 * @param fileNameLength {number} 文件名最大长度
 * @returns {[string, string] | null} [文件名,  扩展名]
 */
export const getFileNameInfo = (fileFullName, fileNameLength = 100) => {
	// const regex = /^([\p{L}\p{N}\p{S} ._-]+)\.(\w+)$/u;
	const regex = /^(.+?)\.([a-zA-Z0-9]+)$/;
	const match = fileFullName.match(regex);
	if (match) {
		const fileName = match[1].length > fileNameLength ? match[1].slice(0, fileNameLength) + '~' : match[1];
		const extension = match[2];
		const fullName = `${fileName}.${extension}`;
		return [fileName, extension, fullName];
	} else {
		return null;
	}
};

/**
 * 获取oss信息
 * @returns {Promise<object>} 阿里云oss信息
 */
export const apiGetOssInfo = () => {
	return new Promise((resolve, reject) => {
		uni.request({
			url: `${baseUrl}${ossPolicyPath}`,
			method: 'GET',
			header: {
				antiShaking: 'true',
				Authorization: `Bearer ${token}`,
				'tenant-id': tenantId,
				'project-id': projectId,
			},
			success: (res) => {
				if (res.data.code === 200) {
					resolve(res.data.data);
				} else {
					resolve();
				}
			},
			fail: (err) => {
				reject(err);
			},
		});
	});
};

/**
 * 根据文件oss相对路径获取文件url
 * @param fileUri {string} oss相对路径
 * @returns {Promise<string>} 文件url
 */
export const apiGetFileUrl = (fileUri) => {
	return new Promise((resolve, reject) => {
		uni.request({
			url: `${baseUrl}${ossFilePath}`,
			method: 'GET',
			data: {
				// TODO
				fileUrl: fileUri,
			},
			header: {
				antiShaking: 'true',
				Authorization: `Bearer ${token}`,
				'tenant-id': tenantId,
				'project-id': projectId,
			},
			success: (res) => {
				resolve(res.data);
			},
			fail: (err) => {
				reject(err);
			},
		});
	});
};

/**
 * 上传文件获取文件url
 * @param file {file} 文件对象
 * @param ossInfo {string} 阿里云oss信息
 * @returns {Promise<object | undefined>} 文件oss信息
 */
export const apiUploadFile = (file, ossInfo) => {
	if (!file || !ossInfo || !ossInfo.host) return undefined;
	const time = dateTimeFormat(new Date(), 'yyyyMMdd');
	const uuid = generateUUID().replace(/-/g, '');
	// TODO
	const fileTargetUri = `${env}/ksmobile/${tenantId}/${projectId}/${time}/${uuid}.${file.fileType}`;
	return new Promise((resolve, reject) => {
		uni.uploadFile({
			url: ossInfo.host,
			name: 'file',
			filePath: file.path || file.tempFilePath,
			header: {
				antiShaking: 'true',
				Authorization: `Bearer ${token}`,
				'tenant-id': tenantId,
				'project-id': projectId,
			},
			formData: {
				name: file.name,
				success_action_status: 204,
				OSSAccessKeyId: ossInfo.accessid,
				signature: ossInfo.signature,
				policy: ossInfo.policy,
				key: fileTargetUri,
			},
			success: async () => {
				const res = await apiGetFileUrl(fileTargetUri);
				resolve({
					url: fileTargetUri,
					fullUrl: res.data,
					uploadTime: dateTimeFormat(new Date()),
				});
			},
			fail: () => {
				reject();
			},
		});
	});
};

/**
 * @description 深度克隆
 * @param obj {object} 需要深度克隆的对象
 * @param cache 缓存
 * @returns {*} 克隆后的对象或者原值（不是对象）
 */
export function deepClone(obj, cache = new WeakMap()) {
	if (obj === null || typeof obj !== 'object') return obj;
	if (cache.has(obj)) return cache.get(obj);
	let clone;
	if (obj instanceof Date) {
		clone = new Date(obj.getTime());
	} else if (obj instanceof RegExp) {
		clone = new RegExp(obj);
	} else if (obj instanceof Map) {
		clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
	} else if (obj instanceof Set) {
		clone = new Set(Array.from(obj, (value) => deepClone(value, cache)));
	} else if (Array.isArray(obj)) {
		clone = obj.map((value) => deepClone(value, cache));
	} else if (Object.prototype.toString.call(obj) === '[object Object]') {
		clone = Object.create(Object.getPrototypeOf(obj));
		cache.set(obj, clone);
		for (const [key, value] of Object.entries(obj)) {
			clone[key] = deepClone(value, cache);
		}
	} else {
		clone = Object.assign({}, obj);
	}
	cache.set(obj, clone);
	return clone;
}
